package main

import "fmt"

// 管道channel是Golang语言级别上提供的goroutine间的通信方式
// 我们可以使用channel在多个goroutine之间传递消息
// channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制
// Golang的并发模型是CSP（Communicating Sequential Process)，提倡通过通信共享内存而不是通过共享内存而实现通信
// channel类似一个传送带或队列，遵循先入先出的规则
// 每一个管道都是具体类型的，声明channel的时候需要为其指定元素类型
// 管道属于引用数据类型，声明后需要make函数初始化后才能使用

/*
	var cha1 chan int
	var cha2 chan []int
	cha1 = make(chan 元素类型, 容量)
*/

func main() {
	// 创建管道并初始化
	var cha1 chan int
	cha1 = make(chan int, 3)
	cha2 := make(chan []int, 3)

	// 发送（将数据放到管道中）
	cha1 <- 10
	cha1 <- 11
	cha1 <- 12
	cha2 <- []int{1, 2, 3}
	cha2 <- []int{4, 5, 6}

	// 接收（从管道内取值）
	val2 := <-cha2
	fmt.Println(<-cha1)
	fmt.Println(val2)

	// 管道的长度和容量
	fmt.Printf("值：%v 容量：%v 长度：%v", cha1, cap(cha1), len(cha1))

	// 管道的堵塞
	// 在没有使用协程的情况下，往容量已满的管道中加数据或空管道中取数据，就会发生堵塞现象
	cha1 <- 13
	// cha1 <- 14 // all goroutines are asleep - deadlock
	<-cha1
	<-cha1
	<-cha1
	// <-cha1 // all goroutines are asleep - deadlock!
}
